﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data.SqlClient;
using WebProxyApplication.WebCache.Entity;
using System.Configuration;


namespace WebProxyApplication.WebCache
{
    public class WebCacheUtil
    {
        /// <summary>
        /// Checks if the URI is contained in the cache
        /// </summary>
        /// <param name="urlToCheck"></param>
        /// <returns>True if the URI is in the cache, False otherwise.</returns>
        public static bool IsKnownSafe(Uri urlToCheck)
        {
            bool retVal = true;
            UriBuilder builder = new UriBuilder(urlToCheck);
            builder.Query = "";
            if(Utils.knownSafeFilter.Contains(builder.Uri.ToString()) == false)
                retVal = false;
            else 
            {
                string conn = System.Configuration.ConfigurationManager.ConnectionStrings["WebProxyConnectionString"].ConnectionString;
                WebProxyDataContext ct = new WebProxyDataContext(conn);
                string s = builder.Uri.ToString();
                Url path = (from a in ct.Urls where a.RawUrl == builder.Uri.ToString()  select a ).FirstOrDefault<Url>();
                if (path == null && (IsKnownSafeGlobal(builder) == false))
                    retVal = false;
            }

            return retVal;
        }

        public static bool IsKnownSafeGlobal(UriBuilder urlToCheck)
        {
            bool retVal = true;
            if (Utils.knownSafeGlobalFilter.Contains(urlToCheck.Uri.ToString()) == false)
                retVal = false;
            else
            {
                Int32 count;
                SqlConnection myConnection = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["GlobalCacheConnectionString"].ConnectionString);
                try
                {
                    myConnection.Open();
                    SqlCommand cmd = new SqlCommand("SELECT COUNT(RawUrl) FROM Url WHERE RawUrl=@url", myConnection);
                    string s = urlToCheck.Uri.ToString();
                    cmd.Parameters.Add(new SqlParameter("@url", urlToCheck.Uri.ToString()));
                    count = (Int32)cmd.ExecuteScalar();
                }
                catch (Exception ex)
                {
                    throw ex;
                }
                finally
                {
                    if (myConnection != null)
                        myConnection.Close();
                }

                if (count < 1)
                    retVal = false;
            }
            return retVal;
        }

        public static void SaveAsSafe(Uri requestedUri)
        {
            UriBuilder builder = new UriBuilder(requestedUri);
            builder.Query = "";
            Uri cleanedUri = builder.Uri;

            SaveAsSafe(cleanedUri, false);
            SaveAsSafe(cleanedUri, true);
            // add to bloom filters
            Utils.knownSafeFilter.Add(cleanedUri.ToString());
            Utils.knownSafeGlobalFilter.Add(cleanedUri.ToString());            
        }

        private static void SaveAsSafe(Uri requestedUri, bool toGlobal)
        {
            Url url = null;
            WebSiteHost wsHost;
            string hostName;
            DateTime now;

            string conn;
            if (toGlobal)
            {
                conn = ConfigurationManager.ConnectionStrings["GlobalCacheConnectionString"].ConnectionString;
            }
            else
            {
                conn = System.Configuration.ConfigurationManager.ConnectionStrings["WebProxyConnectionString"].ConnectionString;
            }
            WebProxyDataContext ct = new WebProxyDataContext(conn);

            hostName = requestedUri.GetComponents(UriComponents.Host, UriFormat.UriEscaped);
            wsHost = (from wsh in ct.WebSiteHosts where wsh.HostName == hostName select wsh).FirstOrDefault<WebSiteHost>();
            if (wsHost == null)
            {
                wsHost = new WebSiteHost();
                wsHost.HostName = hostName;
                wsHost.HostTrustID = 1; // Trusted Host
                ct.WebSiteHosts.InsertOnSubmit(wsHost);
            }

            now = DateTime.Now;

            // create object and fill in fields
            if (toGlobal)
            {
                // the local db should have been checked already (before calling this method) but the global db could already have it, so
                // check to see if it has been added already
                url = (from u in ct.Urls where u.RawUrl == requestedUri.ToString() select u).FirstOrDefault<Url>();
                if (url != null)
                {
                    url.LastAccessDate = now;
                    url.LastModifiedDate = now;
                }
            }

            if (url == null)
            {
                url = new Url();
                url.RawUrl = requestedUri.ToString();
                url.SecurityStatusID = 1;
                url.WebSiteHostID = 1;
                url.PageRank = Utils.getPageRank(requestedUri.ToString());
                url.LastAccessDate = now;
                url.CreatedDate = now;
                url.LastModifiedDate = null; //this can be set once the target is modified

                // connect objects
                url.WebSiteHost = wsHost; // wsHost.Urls.Add(toBeAdded);
                // Add the new object to the Urls collection.
                ct.Urls.InsertOnSubmit(url);
            }

            // Submit the change to the database.
            try
            {
                ct.SubmitChanges();
            }
            catch (Exception e)
            {
                ProxyLogger.Log.Error("Could not add to cache:", e);
            }            
        }

        /*
        /// <summary>
        /// This function is still a work in progress!!
        /// </summary>
        /// <param name="uri"></param>
        public static void SaveAsSafeToGlobal(UriBuilder uri)
        {
            SqlConnection myConnection = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["GlobalCacheConnectionString"].ConnectionString);

            SqlCommand cmd = new SqlCommand();
            cmd.Connection = myConnection;
            // insert only if the URL is not already in the cache
            cmd.CommandText = "INSERT INTO Url (RawUrl, SecurityStatusID, WebSiteHostID, LastAccessDate, CreatedDate) " +
                              "VALUES (@RawUrl, @SecurityStatusID, @WebSiteHostID, @LastAccessDate, @CreatedDate) " +
                                    "SELECT @RawUrl " +
                                "WHERE NOT EXISTS (SELECT RawUrl FROM Url WHERE RawUrl = @RawUrl)"; //NOT WORKING, still inserts duplicates

            //cmd.Parameters.Add(new SqlParameter("@UrlID", -1));  //this is auto-generated when inserting
            cmd.Parameters.Add(new SqlParameter("@RawUrl", uri.Uri.ToString()));
            cmd.Parameters.Add(new SqlParameter("@SecurityStatusID", 1)); 
            cmd.Parameters.Add(new SqlParameter("@WebSiteHostID",1)); //TODO: fix--shouldn't always be 1
            cmd.Parameters.Add(new SqlParameter("@LastAccessDate", System.DateTime.Today));
            cmd.Parameters.Add(new SqlParameter("@CreatedDate", System.DateTime.Now));

            try
            {
                myConnection.Open();                
                cmd.ExecuteNonQuery();
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                if (myConnection != null)
                    myConnection.Close();
            }
        }
        */
    }
}